package com.ydj.framework.interceptor;

import com.ydj.framework.annotation.LogPrinter;
import com.ydj.framework.filter.ExtHttpServletRequest;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

@Slf4j
@Component
public class LogInterceptor extends BaseInterceptor {
	private static final boolean OUTPUT_HEADER = false;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
		if (!(handler instanceof HandlerMethod)) {
			return false;
		}

		if (request instanceof ExtHttpServletRequest) {
			ExtHttpServletRequest extRequest = (ExtHttpServletRequest) request;
			InterceptorContext context = extRequest.getInterceptorContext();

			// 获取注解
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			Method method = handlerMethod.getMethod();
			context.setFunctionNameAnnotation(method.getAnnotation(ApiOperation.class));
			Assert.notNull(context.getFunctionNameAnnotation(), "亲，麻烦在函数上加个ApiOperation注解，用来表示方法的名字，谢谢！");

			context.setLogPrinterAnnotation(method.getAnnotation(LogPrinter.class));

			// 打印日志
			if (!context.getFunctionNameAnnotation().hidden()) {
				boolean printRequest = context.getLogPrinterAnnotation() == null ? true : context.getLogPrinterAnnotation().request();
				String logMsg = createRequestLog(extRequest, printRequest);
				log.info(logMsg);
			}
		}

		return true;
	}

	private String createRequestLog(ExtHttpServletRequest request, boolean printRequest) throws IOException {
		InterceptorContext context = request.getInterceptorContext();
		ApiOperation functionReadme = context.getFunctionNameAnnotation();
		String functionName = functionReadme.value();
		String url = request.getRequestURI();
		String token = request.getToken();
		StringBuilder log = new StringBuilder();
		log.append("请求").append(request.getRequestId())
				.append("【").append(functionName).append("】")
				.append("(").append(url).append(") ")
				.append("token:").append(token);

		// http body
		if (printRequest) {
			String httpMethod = request.getMethod();
			if ("POST".equalsIgnoreCase(httpMethod)) {
				String requestBody = request.getRequestStringForLog();
				if (!StringUtils.isEmpty(requestBody)) {
					log.append(", 请求体:").append(requestBody);
				}
			} else if ("GET".equalsIgnoreCase(httpMethod)) {
				String queryString = request.getQueryString();
				if (!StringUtils.isEmpty(queryString)) {
					log.append(", 请求体:{").append(queryString).append("}");
				}
			}
		}

		if (request.getRequest() instanceof StandardMultipartHttpServletRequest) {
			StandardMultipartHttpServletRequest multiPartRequest = (StandardMultipartHttpServletRequest) request.getRequest();
			Iterator<String> ite = multiPartRequest.getFileNames();
			if (ite.hasNext()) {
				MultipartFile file = multiPartRequest.getFile(ite.next());
				if (file != null) {
					log.append(", 上传文件名:").append(file.getOriginalFilename()).append(", 文件大小:").append(file.getSize() / 1024).append("KB");
				}
			}
		}

		// http header
		if (OUTPUT_HEADER) {
			log.append(", 头:{");
			Enumeration<String> headerNameEnum = request.getHeaderNames();
			while (headerNameEnum.hasMoreElements()) {
				String name = headerNameEnum.nextElement();
				log.append(name).append("=").append(request.getHeader(name));
			}
			log.append("}");
		}
		return log.toString();
	}

}